﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using MeizuSDK.Drawing;
using System.Drawing;
using System.Diagnostics;

namespace MeizuSDK.Presentation
{
    /// <summary>
    /// 列表控件
    /// </summary>
    public class ListBox : ListControlBase
    {
        #region DllImport
        [DllImport("MZFCWrapper.dll")]
        private static extern IntPtr UiListCtor(DrawItemDelegate onDrawItem);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListDrawDefaultItem(IntPtr pObj, IntPtr hdcDst, int nIndex, ref RECT prcItem, ref RECT prcWin, ref RECT prcUpdate);

        [DllImport("MZFCWrapper.dll")]
        private static extern int UiListGetSelectedIndex(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListSetSelectedIndex(IntPtr pObj, int index);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListSetItemHeight(IntPtr pObj, int nHeight);

        [DllImport("MZFCWrapper.dll")]
        private static extern int UiListCalcItemHeight(IntPtr pObj, int index);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListAddItem(IntPtr pObj, [MarshalAsAttribute(UnmanagedType.LPWStr)] string strText);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListRemoveItem(IntPtr pObj, int index);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListRemoveAll(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern int UiListCalcIndexOfPos(IntPtr pObj, uint x, uint y);

        [DllImport("MZFCWrapper.dll")]
        private static extern bool UiListCalcItemRect(IntPtr pObj, int index, ref RECT prcWin, ref RECT pRect);

        [DllImport("MZFCWrapper.dll")]
        private static extern int UiListSwapItem(IntPtr pObj, uint index1, uint index2);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListScrollTo(IntPtr pObj, int nScrollToType, int nDstTopPos, bool bAnimate);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListScrollStart(IntPtr pObj, double fScrollSpeed);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListScrollStop(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListEnableGridlines(IntPtr pObj, bool bEnable);

        [DllImport("MZFCWrapper.dll")]
        private static extern bool UiListIsGridlinesEnabled(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListEnableUltraGridlines(IntPtr pObj, bool bEnable);

        [DllImport("MZFCWrapper.dll")]
        private static extern bool UiListIsUltraGridlinesEnabled(IntPtr pObj);

        [DllImport("MZFCWrapper.dll")]
        private static extern void UiListInvalidateItem(IntPtr pObj, int index);
        #endregion

        #region 私有变量
        /// <summary>
        /// 默认列表项高度
        /// </summary>
        private int defaultItemHeight;
        /// <summary>
        /// 列表项绘制函数委托
        /// </summary>
        private DrawItemDelegate drawItemDelegate;
        #endregion

        #region 公共属性
        /// <summary>
        /// 获取或设置列表当前选中的项索引
        /// </summary>
        public override int SelectedIndex
        {
            get
            {
                return UiListGetSelectedIndex(Handle);
            }
            set
            {
                if (value > 0 || value < Items.Count)
                {
                    Items.SetItemSelected(value, true);
                    UiListSetSelectedIndex(Handle, value);
                    InternalItemSelect(value);
                    InvalidateItem(value);
                    Update();
                }
            }
        }
        /// <summary>
        /// 获取或设置列表项默认高度
        /// </summary>
        public override int DefaultItemHeight
        {
            get
            {
                return defaultItemHeight;
            }
            set
            {
                if (value != this.defaultItemHeight)
                {
                    this.defaultItemHeight = value;
                    UiListSetItemHeight(Handle, value);
                }
            }
        }
        /// <summary>
        /// 获取或设置一个标志，指示列表是否绘制列表线
        /// </summary>
        public override bool GridLines
        {
            get
            {
                return UiListIsGridlinesEnabled(Handle);
            }
            set
            {
                UiListEnableGridlines(Handle, value);
            }
        }
        /// <summary>
        /// 获取或设置一个标志，指示列表是否绘制额外列表线
        /// </summary>
        public override bool UltraGridLines
        {
            get
            {
                return UiListIsUltraGridlinesEnabled(Handle);
            }
            set
            {
                UiListEnableUltraGridlines(Handle, value);
            }
        }
        #endregion

        #region 构造函数
        /// <summary>
        /// 构建列表控件
        /// </summary>
        public ListBox()
        {
            drawItemDelegate = new DrawItemDelegate(InternalDrawItem);

            Handle = UiListCtor(drawItemDelegate);
            SetID();
            NotifyMessage = true;// 默认启用鼠标通知
            DefaultItemHeight = 70;// 列表项默认高度
        }
        #endregion

        #region 函数

        #region 内部函数
        /// <summary>
        /// 添加列表项
        /// </summary>
        /// <param name="text">列表项文本</param>
        internal override void AddItem(string text)
        {
            UiListAddItem(Handle, text);
        }
        /// <summary>
        /// 移除指定索引的列表项
        /// </summary>
        /// <param name="index"></param>
        internal override void RemoveItem(int index)
        {
            UiListRemoveItem(Handle, index);
        }
        /// <summary>
        /// 移除所有的列表项
        /// </summary>
        internal override void RemoveAllItems()
        {
            UiListRemoveAll(Handle);
        }
        #endregion

        /// <summary>
        /// 绘制默认列表项
        /// </summary>
        /// <param name="hdcDst">设备上下文句柄</param>
        /// <param name="nIndex">待绘制的列表项索引</param>
        /// <param name="prcItem">列表项所在矩形</param>
        /// <param name="prcWin">列表控件所在矩形</param>
        /// <param name="prcUpdate">待更新的矩形区域</param>
        protected override void DrawDefaultItem(IntPtr hdcDst, int nIndex, ref RECT prcItem, ref RECT prcWin, ref RECT prcUpdate)
        {
            UiListDrawDefaultItem(Handle, hdcDst, nIndex, ref prcItem, ref prcWin, ref prcUpdate);
        }
        /// <summary>
        /// 获取指定索引处的列表项高度
        /// </summary>
        /// <param name="index">列表项索引</param>
        /// <returns>返回此列表项高度</returns>
        public override int GetItemHeight(int index)
        {
            return UiListCalcItemHeight(Handle, index);
        }
        /// <summary>
        /// 开始滚动
        /// </summary>
        /// <param name="scrollSpeed">滚动速度</param>
        public override void ScrollStart(double scrollSpeed)
        {
            UiListScrollStart(Handle, scrollSpeed);
        }
        /// <summary>
        /// 停止滚动
        /// </summary>
        public override void ScrollStop()
        {
            UiListScrollStop(Handle);
        }
        /// <summary>
        /// 滚动列表内容到指定位置
        /// </summary>
        /// <param name="scrollType">滚动类型</param>
        /// <param name="dstTopPos">目的为止。当ScrollType=ScrollToPos时才有效</param>
        /// <param name="animate">是否显示滚动过程</param>
        public override void ScrollTo(ScrollType scrollType, int dstTopPos, bool animate)
        {
            UiListScrollTo(Handle, (int)scrollType, dstTopPos, animate);
        }

        /// <summary>
        /// 计算某一坐标出的列表项的索引
        /// </summary>
        /// <param name="xPos"></param>
        /// <param name="yPos"></param>
        /// <returns></returns>
        public override int CalcItemIndexOfPos(int xPos, int yPos)
        {
            return UiListCalcIndexOfPos(Handle, (uint)xPos, (uint)yPos);
        }
        /// <summary>
        /// 计算指定索引的列表项所在矩形区域
        /// </summary>
        /// <param name="index">列表项索引</param>
        /// <returns></returns>
        public override Rectangle CalcItemRectangle(int index)
        {
            RECT prcWin = RECT.FromXYWH(X, Y, Width, Height);
            RECT itemRect = new RECT();

            UiListCalcItemRect(Handle, index, ref prcWin, ref itemRect);

            return itemRect.ToRectangle();
        }
        /// <summary>
        /// 将指定索引的列表项设置为无效，在下次刷新时会重绘
        /// </summary>
        /// <param name="index">列表项索引</param>
        public override void InvalidateItem(int index)
        {
            if (index < 0 || index >= Items.Count)
                return;
            UiListInvalidateItem(Handle, index);
        }
        /// <summary>
        /// 鼠标左键按下消息
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLButtonDown(MouseEventArgs e)
        {
             LastX = e.X;
            LastY = e.Y;

            int index = CalcItemIndexOfPos(e.X, e.Y);

            if (ContainsItem(index))
            {
                MouseDown = true;
                LastClickedIndex = index;
                InvalidateItem(LastClickedIndex);
            }
            else
            {
                MouseDown = false;
                LastClickedIndex = -1;
                Invalidate();
            }

            Update();

            base.OnLButtonDown(e);
        }
        /// <summary>
        /// 鼠标左键抬起消息
        /// </summary>
        /// <param name="e"></param>
        protected override void OnLButtonUp(MouseEventArgs e)
        {
            if (e.X != LastX || e.Y != LastY)
            {
                if (MouseDown)
                {
                    MouseDown = false;
                    LastClickedIndex = -1;
                    Invalidate();
                    Update();
                }
                return;
            }

            MouseDown = false;

            int index = CalcItemIndexOfPos(e.X, e.Y);

            if (ContainsItem(index))
            {
                LastClickedIndex = index;
                SelectedIndex = index;
                base.OnLButtonUp(e);
                OnClick(new ListBoxClickEventArgs(index));
                return;
            }
            else
            {
                LastClickedIndex = -1;
                Invalidate();
                Update();
                base.OnLButtonUp(e);
            }
        }
        #endregion
    }
}
